package service

import (
	"fmt"
	"log"
	"net/url"
	"time"

	"github.com/yourusername/rss-reader-ai/internal/fetcher"
	"github.com/yourusername/rss-reader-ai/internal/model"
	"github.com/yourusername/rss-reader-ai/internal/repository"
)

// =====================================================
// FeedService 接口定义
// =====================================================

// FeedService 订阅源业务逻辑接口
type FeedService interface {
	// AddFeed 添加订阅源
	// 会验证URL格式、检查重复
	AddFeed(url, title, category string) (*model.Feed, error)

	// GetFeed 获取订阅源详情
	GetFeed(id int64) (*model.Feed, error)

	// ListFeeds 获取所有订阅源
	ListFeeds() ([]*model.Feed, error)

	// ListFeedsByCategory 根据分类获取订阅源
	ListFeedsByCategory(category string) ([]*model.Feed, error)

	// UpdateFeed 更新订阅源
	UpdateFeed(id int64, title, category string, interval int) error

	// DeleteFeed 删除订阅源
	// 会级联删除所有文章
	DeleteFeed(id int64) error

	// ToggleFeedStatus 切换订阅源启用状态
	ToggleFeedStatus(id int64) error

	// RefreshFeed 手动刷新订阅源
	// 立即抓取最新文章，返回新增文章数
	RefreshFeed(id int64) (int, error)

	// RefreshAllFeeds 手动刷新所有启用的订阅源
	// 并发抓取，返回统计信息
	RefreshAllFeeds() (*RefreshAllResult, error)

	// GetFeedStats 获取订阅源统计信息
	GetFeedStats() (*FeedStats, error)
}

// RefreshAllResult 全量刷新结果
type RefreshAllResult struct {
	Total        int           `json:"total"`         // 总数
	Success      int           `json:"success"`       // 成功数
	Failed       int           `json:"failed"`        // 失败数
	NewArticles  int           `json:"new_articles"`  // 新增文章总数
	Duration     time.Duration `json:"duration"`      // 耗时
	FailedFeeds  []FailedFeed  `json:"failed_feeds"`  // 失败的 Feed 列表
}

// FailedFeed 失败的订阅源信息
type FailedFeed struct {
	ID    int64  `json:"id"`
	Title string `json:"title"`
	Error string `json:"error"`
}

// FeedStats 订阅源统计信息
type FeedStats struct {
	TotalFeeds     int64            // 总订阅源数
	ActiveFeeds    int64            // 启用的订阅源数
	CategoryCounts map[string]int64 // 每个分类的订阅源数
}

// =====================================================
// FeedService 接口实现
// =====================================================

// feedService 订阅源业务逻辑实现
type feedService struct {
	feedRepo    repository.FeedRepository
	articleRepo repository.ArticleRepository
	fetcher     fetcher.Fetcher
}

// NewFeedService 创建订阅源业务逻辑实例
func NewFeedService(
	feedRepo repository.FeedRepository,
	articleRepo repository.ArticleRepository,
) FeedService {
	// 创建 Fetcher 实例 (30秒超时)
	rssFetcher := fetcher.NewFetcher(30*time.Second, "RSS Reader AI/1.0")
	
	return &feedService{
		feedRepo:    feedRepo,
		articleRepo: articleRepo,
		fetcher:     rssFetcher,
	}
}

// AddFeed 添加订阅源
func (s *feedService) AddFeed(feedURL, title, category string) (*model.Feed, error) {
	// 1. 验证URL格式
	if err := s.validateURL(feedURL); err != nil {
		return nil, fmt.Errorf("无效的URL: %w", err)
	}

	// 2. 检查URL是否已存在
	existingFeed, _ := s.feedRepo.GetByURL(feedURL)
	if existingFeed != nil {
		return nil, fmt.Errorf("订阅源已存在: %s", feedURL)
	}

	// 3. 设置默认值
	if title == "" {
		title = feedURL // 如果没有标题,使用URL作为标题
	}
	if category == "" {
		category = "未分类"
	}

	// 4. 创建订阅源
	feed := &model.Feed{
		URL:           feedURL,
		Title:         title,
		Category:      category,
		FetchInterval: 3600, // 默认1小时
		IsActive:      true,
	}

	if err := s.feedRepo.Create(feed); err != nil {
		return nil, fmt.Errorf("创建订阅源失败: %w", err)
	}

	log.Printf("✅ 添加订阅源成功: %s (%s)", feed.Title, feed.URL)
	return feed, nil
}

// GetFeed 获取订阅源详情
func (s *feedService) GetFeed(id int64) (*model.Feed, error) {
	feed, err := s.feedRepo.GetByID(id)
	if err != nil {
		return nil, fmt.Errorf("获取订阅源失败: %w", err)
	}
	return feed, nil
}

// ListFeeds 获取所有订阅源
func (s *feedService) ListFeeds() ([]*model.Feed, error) {
	feeds, err := s.feedRepo.List()
	if err != nil {
		return nil, fmt.Errorf("获取订阅源列表失败: %w", err)
	}
	return feeds, nil
}

// ListFeedsByCategory 根据分类获取订阅源
func (s *feedService) ListFeedsByCategory(category string) ([]*model.Feed, error) {
	feeds, err := s.feedRepo.ListByCategory(category)
	if err != nil {
		return nil, fmt.Errorf("获取分类订阅源失败: %w", err)
	}
	return feeds, nil
}

// UpdateFeed 更新订阅源
func (s *feedService) UpdateFeed(id int64, title, category string, interval int) error {
	// 1. 检查订阅源是否存在
	feed, err := s.feedRepo.GetByID(id)
	if err != nil {
		return fmt.Errorf("订阅源不存在: %w", err)
	}

	// 2. 更新字段
	if title != "" {
		feed.Title = title
	}
	if category != "" {
		feed.Category = category
	}
	if interval > 0 {
		feed.FetchInterval = interval
	}

	// 3. 保存更新
	if err := s.feedRepo.Update(feed); err != nil {
		return fmt.Errorf("更新订阅源失败: %w", err)
	}

	log.Printf("✅ 更新订阅源成功: %s", feed.Title)
	return nil
}

// DeleteFeed 删除订阅源
func (s *feedService) DeleteFeed(id int64) error {
	// 1. 检查订阅源是否存在
	feed, err := s.feedRepo.GetByID(id)
	if err != nil {
		return fmt.Errorf("订阅源不存在: %w", err)
	}

	// 2. 删除订阅源(级联删除文章)
	if err := s.feedRepo.Delete(id); err != nil {
		return fmt.Errorf("删除订阅源失败: %w", err)
	}

	log.Printf("✅ 删除订阅源成功: %s (%d篇文章)", feed.Title, feed.ArticleCount)
	return nil
}

// ToggleFeedStatus 切换订阅源启用状态
func (s *feedService) ToggleFeedStatus(id int64) error {
	// 1. 获取当前状态
	feed, err := s.feedRepo.GetByID(id)
	if err != nil {
		return fmt.Errorf("订阅源不存在: %w", err)
	}

	// 2. 切换状态
	newStatus := !feed.IsActive
	if err := s.feedRepo.UpdateFields(id, map[string]interface{}{
		"is_active": newStatus,
	}); err != nil {
		return fmt.Errorf("切换状态失败: %w", err)
	}

	status := "启用"
	if !newStatus {
		status = "禁用"
	}
	log.Printf("✅ %s订阅源: %s", status, feed.Title)
	return nil
}

// RefreshFeed 手动刷新订阅源，返回新增文章数
func (s *feedService) RefreshFeed(id int64) (int, error) {
	// 1. 检查订阅源是否存在
	feed, err := s.feedRepo.GetByID(id)
	if err != nil {
		return 0, fmt.Errorf("订阅源不存在: %w", err)
	}

	if !feed.IsActive {
		return 0, fmt.Errorf("订阅源已禁用,无法刷新")
	}

	log.Printf("📡 开始刷新订阅源: %s (%s)", feed.Title, feed.URL)

	// 2. 使用 Fetcher 抓取 RSS 内容
	feedData, err := s.fetcher.FetchFeed(feed.URL)
	if err != nil {
		return 0, fmt.Errorf("抓取 RSS 失败: %w", err)
	}

	// 3. 更新订阅源信息(标题、描述、图标等)
	if feedData.Title != "" && feedData.Title != feed.Title {
		feed.Title = feedData.Title
	}
	if feedData.Description != "" {
		feed.Description = feedData.Description
	}
	if feedData.SiteURL != "" {
		feed.SiteURL = feedData.SiteURL
	}
	if feedData.IconURL != "" {
		feed.IconURL = feedData.IconURL
	}

	// 4. 保存订阅源更新
	now := time.Now()
	if err := s.feedRepo.UpdateFields(id, map[string]interface{}{
		"title":            feed.Title,
		"description":      feed.Description,
		"site_url":         feed.SiteURL,
		"icon_url":         feed.IconURL,
		"last_fetched_at":  now,
	}); err != nil {
		return 0, fmt.Errorf("更新订阅源信息失败: %w", err)
	}

	// 5. 处理文章列表(去重 + 保存)
	newCount, err := s.saveArticles(id, feedData.Articles)
	if err != nil {
		return 0, fmt.Errorf("保存文章失败: %w", err)
	}

	log.Printf("✅ 刷新完成: %s, 新增文章: %d 篇", feed.Title, newCount)
	return newCount, nil
}

// RefreshAllFeeds 手动刷新所有启用的订阅源（并发 + 重试）
func (s *feedService) RefreshAllFeeds() (*RefreshAllResult, error) {
	startTime := time.Now()
	
	// 获取所有启用的订阅源
	feeds, err := s.feedRepo.GetActiveFeeds()
	if err != nil {
		return nil, fmt.Errorf("获取订阅源列表失败: %w", err)
	}

	if len(feeds) == 0 {
		return &RefreshAllResult{
			Total:    0,
			Success:  0,
			Failed:   0,
			Duration: time.Since(startTime),
		}, nil
	}

	// 使用 channel 控制并发数（最多5个并发）
	const maxConcurrency = 5
	semaphore := make(chan struct{}, maxConcurrency)
	
	// 结果收集
	type result struct {
		success     bool
		feedID      int64
		feedTitle   string
		newArticles int
		err         error
	}
	results := make(chan result, len(feeds))

	// 并发抓取所有 Feed
	for _, feed := range feeds {
		semaphore <- struct{}{}  // 获取令牌
		
		go func(f *model.Feed) {
			defer func() { <-semaphore }()  // 释放令牌
			
			// 重试逻辑：最多尝试 3 次
			var newCount int
			var err error
			maxRetries := 3
			
			for attempt := 1; attempt <= maxRetries; attempt++ {
				newCount, err = s.RefreshFeed(f.ID)
				
				if err == nil {
					results <- result{
						success:     true,
						feedID:      f.ID,
						feedTitle:   f.Title,
						newArticles: newCount,
					}
					return
				}
				
				// 指数退避：1秒 → 2秒 → 4秒
				if attempt < maxRetries {
					backoff := time.Duration(1<<uint(attempt-1)) * time.Second
					time.Sleep(backoff)
				}
			}
			
			// 所有重试都失败
			results <- result{
				success:   false,
				feedID:    f.ID,
				feedTitle: f.Title,
				err:       err,
			}
		}(feed)
	}

	// 等待所有任务完成并收集结果
	successCount := 0
	failCount := 0
	totalNewArticles := 0
	var failedFeeds []FailedFeed
	
	for i := 0; i < len(feeds); i++ {
		res := <-results
		
		if res.success {
			successCount++
			totalNewArticles += res.newArticles
			log.Printf("✅ [手动刷新] 成功: %s, 新增: %d 篇", res.feedTitle, res.newArticles)
		} else {
			failCount++
			failedFeeds = append(failedFeeds, FailedFeed{
				ID:    res.feedID,
				Title: res.feedTitle,
				Error: res.err.Error(),
			})
			log.Printf("❌ [手动刷新] 失败: %s, 错误: %v", res.feedTitle, res.err)
		}
	}

	return &RefreshAllResult{
		Total:       len(feeds),
		Success:     successCount,
		Failed:      failCount,
		NewArticles: totalNewArticles,
		Duration:    time.Since(startTime),
		FailedFeeds: failedFeeds,
	}, nil
}

// saveArticles 保存文章列表(自动去重)
func (s *feedService) saveArticles(feedID int64, articles []*fetcher.ArticleData) (int, error) {
	newCount := 0

	for _, articleData := range articles {
		// 1. 检查文章是否已存在(根据 feed_id + guid 去重)
		exists, err := s.articleRepo.ExistsByFeedAndGUID(feedID, articleData.GUID)
		if err != nil {
			log.Printf("⚠️  检查文章是否存在失败: %v", err)
			continue
		}

		// 2. 如果文章已存在,跳过
		if exists {
			continue
		}

		// 3. 转换为 Article 模型
		article := articleData.ToArticle(feedID)

		// 4. 保存到数据库
		if err := s.articleRepo.Create(article); err != nil {
			log.Printf("⚠️  保存文章失败: %s, 错误: %v", article.Title, err)
			continue
		}

		newCount++
		log.Printf("✅ 新增文章: %s", article.Title)
	}

	return newCount, nil
}

// GetFeedStats 获取订阅源统计信息
func (s *feedService) GetFeedStats() (*FeedStats, error) {
	// 1. 统计总数
	total, err := s.feedRepo.Count()
	if err != nil {
		return nil, fmt.Errorf("统计订阅源失败: %w", err)
	}

	// 2. 统计启用的订阅源
	activeFeeds, err := s.feedRepo.ListActive()
	if err != nil {
		return nil, fmt.Errorf("统计启用订阅源失败: %w", err)
	}

	// 3. 统计每个分类的数量
	categoryCounts := make(map[string]int64)
	feeds, err := s.feedRepo.List()
	if err != nil {
		return nil, fmt.Errorf("获取订阅源列表失败: %w", err)
	}

	for _, feed := range feeds {
		categoryCounts[feed.Category]++
	}

	return &FeedStats{
		TotalFeeds:     total,
		ActiveFeeds:    int64(len(activeFeeds)),
		CategoryCounts: categoryCounts,
	}, nil
}

// =====================================================
// 私有辅助方法
// =====================================================

// validateURL 验证URL格式
func (s *feedService) validateURL(urlStr string) error {
	if urlStr == "" {
		return fmt.Errorf("URL不能为空")
	}

	// 解析URL
	parsedURL, err := url.Parse(urlStr)
	if err != nil {
		return fmt.Errorf("URL格式错误: %w", err)
	}

	// 检查协议
	if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
		return fmt.Errorf("URL必须是http或https协议")
	}

	// 检查主机
	if parsedURL.Host == "" {
		return fmt.Errorf("URL必须包含主机名")
	}

	return nil
}
